/**
 * @param path 通过自定义的路径获取到对应的值
 * @param obj 取值的目标对象
 * @returns
 */
// eslint-disable-next-line no-unused-vars
const jsonPath = (path = '', obj) => {
  const paths = path.split('.');
  for (const k of paths) {
    obj = getValueByObj(k, obj);
  }
  return obj;
};

/**
 *
 * @param jsonPath
 * @param obj
 * @param setValue
 */
// eslint-disable-next-line no-unused-vars
const setValueByJsonPath = (  jsonPath,  obj,  setValue) => {
  const paths = jsonPath.split('.');
  const newObj = { ...obj };
  const pathSet = new Array();
  for (let index = 0; index < paths.length; index++) {
    const key = paths[index];
    if (index == paths.length - 1) {
      //@ts-ignore
      pathSet.push({
        key,
        obj: setValue
      });
    } else {
      obj = getValueByObj(key, obj);
      pathSet.push({
        key,
        obj
      });
    }
  }
  // 将 pathSet中的值 组装成一个新的对象
  const testObj = {};
  const length = pathSet.length;
  for (let index = 0; index < length; index++) {
    const item = pathSet.pop();
    const testObjKeys = Object.keys(testObj);
    if (testObjKeys.length <= 0) {
      testObj[item.key] = item.obj;
    } else {
      testObjKeys.map((key) => {
        item.obj[key] = testObj[key];
        delete testObj[key];
      });
      testObj[item.key] = item.obj;
    }
  }

  return { ...newObj, ...testObj };
};

/**
 *
 * @param obj
 * @param index
 * @param key
 * @param resObj
 */
const transformJsonPaths = (obj, index = 0, key , resObj = []) => {
  Object.keys(obj).map((o, i) => {
    //@ts-ignore
    const ochild = obj[o];
    if (
      ochild != null &&
      typeof ochild == 'object' &&
      Object.keys(o).length >= 0
    ) {
      // try{
      transformJsonPaths(ochild, index + 1, key + '.' + o, resObj);
      // }catch(err){
      //   console.log(err,ochild, index + 1, key + "." + o ,resObj)
      // }
    } else {
      // 拿出最后一位
      const res = {
        key: o,
        value: ochild,
        deep: index,
        path: key + '.' + o
      };
      resObj.push(res);
    }
  });

  return resObj;
};

const diffChanges = (params, res) => {
  let arr = [];
  res.forEach((r) => {
    const diff = params.filter(
      (paramItem) => r.key == paramItem.key && r.value == paramItem.value
    );
    if(diff.length>0){
      arr= arr.concat(diff);
    }
  });

  return arr.length >0 ? arr : null ;
};

const getValueByObj = (key, o) => {
  if (o && Object.keys(o).includes(key)) {
    return o[key];
  } else {
    throw new Error(`keys error : ${key}`);
  }
};



const generatorFeature = (sessions)=>{

  const length = sessions.length;
  // console.log('接口共->', length)
  let preArr = [];
  const changesParams = sessions.map((item) => {
    return Object.keys(item.params).length >0 ?
       transformJsonPaths(item.params, 1, 'params')
      :[null];
  });
  const changesResList = sessions.map((item) => {
    try {
      return transformJsonPaths(item.res, 1, 'res');
    }catch (e) {
      console.log(e.message);
      return [null];
    }
  });

  for (let index = 0; index < length; index++) {
    let paramsElLength = changesParams.length;
    const paramsEl = changesParams.pop();
    paramsElLength--;
    changesResList.pop();
    const itemList =  [];
    changesResList.map((item, i) => {
      const resUrl = sessions[i].url;
      const paramsUrl = sessions[paramsElLength].url;
      if (resUrl != paramsUrl) {
        const t = diffChanges(item, paramsEl);
        if (t) {
          // diff 过滤
          const n = t.reduce((pre, currentValue) => {
            const dr = pre.find((i) => i.key == currentValue.key && i.value == currentValue.value);
            if (dr) {
              return pre;
            } else {
              return pre.concat(currentValue);
            }
          }, []);
          const diffres = {
            resUrl: resUrl,
            paramsUrl: paramsUrl,
            diffRes: n,
            paramsIndex: paramsElLength,
            resIndex: i
          };
          itemList.push(diffres);
        }
      } else {
        return;
      }
    });
    preArr = preArr.concat(itemList);
  }


  // list to Feature
  const feature = [];
  const paramsENV = [];
  const resSetENV= [];
  const features = sessions.map((f) => {
    const pl = preArr.filter(o => f.url == o.paramsUrl);
    if (pl.length >= 1) {
      pl.forEach(li => {
        li.diffRes.map((d) => {
          f.params[d.key] = `\${${d.key}}`;
          paramsENV.push({key:d.key,value:d.value})
        });
      });
    }

    feature.push(`Scenario: ${f.url}`);
    feature.push(` Given api ${f.url}`);
    feature.push(' When params:');
    feature.push('     """');
    feature.push(`${JSON.stringify(f.params)}`);
    feature.push('     """');
    feature.push(' When post');
    feature.push(' Then status 200');
    try{
      feature.push(` Then assert $.code equals ${f.res.code}`);
    }catch(err){
      console.log(err.message);
    }
    // feature.push(`# res : ${JSON.stringify(f.res)} \n\n`)
    // const str = feature.join('\n')

    const rl = preArr.filter(o => f.url == o.resUrl);
    if (rl.length >= 1) {
      rl.forEach(li => {
        li.diffRes.map((d) => {
          const env = ` Then set_env $.${d.path} tobe ${d.key} `;
          const isSet = resSetENV.find(env=> env.key == d.key && env.value ==d.value );
          if (!feature[feature.length - 1].includes(env) && isSet == undefined) {
            feature.push(env);
            resSetENV.push({path:d.path,key:d.key,value:d.value})
          }
        });
      });
    }
    feature.push('\n');
    const str = feature.join('\n');
    return str;
  });
  console.log('features=> changdu : @',features.length);
  return features;
};


module.exports = { generatorFeature };
